import type { KeyboardEvent, FocusEvent } from "react";
import { Box, Flex, styled, Text } from "@webstudio-is/design-system";
import { UploadingAnimation } from "./uploading-animation";
import { ImageInfo, imageInfoCssVars } from "./image-info";
import type { AssetContainer } from "~/builder/shared/assets";
import { Image } from "./image";
import brokenImage from "~/shared/images/broken-image-placeholder.svg";
import { theme } from "@webstudio-is/design-system";
import {
  formatAssetName,
  isVideoFormat,
  parseAssetName,
} from "../assets/asset-utils";

const StyledWebstudioImage = styled(Image, {
  position: "absolute",
  width: "100%",
  height: "100%",
  objectFit: "contain",

  // This is shown only if an image was not loaded and broken
  // From the spec:
  // - The pseudo-elements generated by ::before and ::after are contained by the element's formatting box,
  //   and thus don't apply to "replaced" elements such as <img>, or to <br> elements
  // Not in spec but supported by all browsers:
  // - broken image is not a "replaced" element so this style is applied
  "&::after": {
    content: "' '",
    position: "absolute",
    width: "100%",
    height: "100%",
    left: 0,
    top: 0,
    backgroundSize: "contain",
    backgroundRepeat: "no-repeat",
    backgroundPosition: "center",
    backgroundImage: `url(${brokenImage})`,
  },
});

const StyledWebstudioVideo = styled("video", {
  position: "absolute",
  width: "100%",
  height: "100%",
  objectFit: "contain",

  // This is shown only if an image was not loaded and broken
  // From the spec:
  // - The pseudo-elements generated by ::before and ::after are contained by the element's formatting box,
  //   and thus don't apply to "replaced" elements such as <img>, or to <br> elements
  // Not in spec but supported by all browsers:
  // - broken image is not a "replaced" element so this style is applied
  "&::after": {
    content: "' '",
    position: "absolute",
    width: "100%",
    height: "100%",
    left: 0,
    top: 0,
    backgroundSize: "contain",
    backgroundRepeat: "no-repeat",
    backgroundPosition: "center",
    backgroundImage: `url(${brokenImage})`,
  },
});

const ThumbnailContainer = styled(Box, {
  position: "relative",
  display: "flex",
  justifyContent: "center",
  alignItems: "center",
  flexDirection: "column",
  borderRadius: theme.borderRadius[4],
  outline: "none",
  gap: theme.spacing[3],
  overflow: "hidden",
  padding: 2,
  "&:hover": {
    ...imageInfoCssVars({ show: true }),
    backgroundColor: theme.colors.backgroundAssetcardHover,
  },
  variants: {
    status: {
      uploading: {},
      uploaded: {},
      deleting: {},
    },
    state: {
      selected: {
        outline: `1px solid ${theme.colors.borderFocus}`,
        outlineOffset: -1,
        backgroundColor: theme.colors.backgroundAssetcardHover,
        ...imageInfoCssVars({ show: true }),
      },
    },
  },
});

const Thumbnail = styled(Box, {
  width: "100%",
  height: theme.spacing[19],
  flexShrink: 0,
  position: "relative",
});

type ImageThumbnailProps = {
  assetContainer: AssetContainer;
  onSelect: (assetContainer?: AssetContainer) => void;
  onChange?: (assetContainer: AssetContainer) => void;
  state?: "selected";
};

export const ImageThumbnail = ({
  assetContainer,
  onSelect,
  onChange,
  state,
}: ImageThumbnailProps) => {
  const { asset } = assetContainer;
  const { basename, ext } = parseAssetName(asset.name);
  const alt = asset.description ?? formatAssetName(asset);
  const isUploading = assetContainer.status === "uploading";

  return (
    <ThumbnailContainer
      title={alt}
      tabIndex={0}
      status={assetContainer.status}
      state={state}
      onFocus={() => {
        onSelect?.(assetContainer);
      }}
      onBlur={(event: FocusEvent) => {
        const isFocusWithin = event.currentTarget.contains(event.relatedTarget);
        if (isFocusWithin === false) {
          onSelect();
        }
      }}
      onKeyDown={(event: KeyboardEvent) => {
        if (event.code === "Enter") {
          onChange?.(assetContainer);
        }
      }}
    >
      <Thumbnail
        onClick={() => {
          onChange?.(assetContainer);
        }}
      >
        {isVideoFormat(asset.format) &&
        assetContainer.status === "uploading" ? (
          <StyledWebstudioVideo width={64} src={assetContainer.objectURL} />
        ) : (
          <StyledWebstudioImage
            assetId={asset.id}
            name={asset.name}
            objectURL={
              assetContainer.status === "uploading"
                ? assetContainer.objectURL
                : undefined
            }
            alt={alt}
            // width={64} used for Image optimizations it should be approximately equal to the width of the picture on the screen in px
            width={64}
          />
        )}
      </Thumbnail>
      <Flex css={{ width: "100%", paddingBottom: 4 }}>
        <Text variant="tiny" truncate>
          {asset.filename ?? basename}
        </Text>
        <Text variant="tiny">.{ext}</Text>
      </Flex>
      {assetContainer.status === "uploaded" && (
        <ImageInfo asset={assetContainer.asset} />
      )}
      {isUploading && <UploadingAnimation />}
    </ThumbnailContainer>
  );
};
